From: Keir Fraser Date: Thu, 8 May 2008 10:15:58 +0000 (+0100) Subject: xend: Improve "cpus" parameter to be able to define CPU affinities for each VCPU X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14215^2~51 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=ef4c89d29430fa2e300cafeeb64c3e635f672d29;p=xen.git xend: Improve "cpus" parameter to be able to define CPU affinities for each VCPU If we define the form of list of string to "cpus" parameter, different CPU affinities are set for each VCPU as follows. # grep cpus /etc/xen/vm1 cpus = ["2", "3"] vcpus = 2 # xm create vm1 Using config file "/etc/xen/vm1". Started domain vm1 # xm vcpu-list vm1 Name ID VCPU CPU State Time(s) CPU Affinity vm1 1 0 2 r-- 3.5 2 vm1 1 1 3 -b- 3.2 3 If we define the form of string to "cpus" parameter as before, a same CPU affinity is set for each VCPU as follows. # grep cpus /etc/xen/vm2 cpus = "2,3" vcpus = 2 # xm create vm2 Using config file "/etc/xen/vm2". Started domain vm2 # xm vcpu-list vm2 Name ID VCPU CPU State Time(s) CPU Affinity vm2 2 0 3 -b- 3.0 2-3 vm2 2 1 2 r-- 2.6 2-3 Signed-off-by: Masaki Kanno --- diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 8a4deacf57..cdb4c1c6f3 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -640,46 +640,84 @@ class XendConfig(dict): else: cfg['cpus'] = str(cfg['cpu']) - # Convert 'cpus' to list of ints + # Convert 'cpus' to list of list of ints + cpus_list = [] if 'cpus' in cfg: - cpus = [] + # Convert the following string to list of ints. + # The string supports a list of ranges (0-3), + # seperated by commas, and negation (^1). + # Precedence is settled by order of the string: + # "0-3,^1" -> [0,2,3] + # "0-3,^1,1" -> [0,1,2,3] + def cnv(s): + l = [] + for c in s.split(','): + if c.find('-') != -1: + (x, y) = c.split('-') + for i in range(int(x), int(y)+1): + l.append(int(i)) + else: + # remove this element from the list + if c[0] == '^': + l = [x for x in l if x != int(c[1:])] + else: + l.append(int(c)) + return l + if type(cfg['cpus']) == list: - # If sxp_cfg was created from config.sxp, - # the form of 'cpus' is list of string. - # Convert 'cpus' to list of ints. - # ['1'] -> [1] - # ['0','2','3'] -> [0,2,3] - try: - for c in cfg['cpus']: - cpus.append(int(c)) - - cfg['cpus'] = cpus - except ValueError, e: - raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) + if len(cfg['cpus']) > 0 and type(cfg['cpus'][0]) == list: + # If sxp_cfg was created from config.sxp, + # the form of 'cpus' is list of list of string. + # Convert 'cpus' to list of list of ints. + # Conversion examples: + # [['1']] -> [[1]] + # [['0','2'],['1','3']] -> [[0,2],[1,3]] + try: + for c1 in cfg['cpus']: + cpus = [] + for c2 in c1: + cpus.append(int(c2)) + cpus_list.append(cpus) + except ValueError, e: + raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) + else: + # Conversion examples: + # ["1"] -> [[1]] + # ["0,2","1,3"] -> [[0,2],[1,3]] + # ["0-3,^1","1-4,^2"] -> [[0,2,3],[1,3,4]] + try: + for c in cfg['cpus']: + cpus = cnv(c) + cpus_list.append(cpus) + except ValueError, e: + raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) + + if len(cpus_list) != cfg['vcpus']: + raise XendConfigError('vcpus and the item number of cpus are not same') else: - # Convert 'cpus' string to list of ints - # 'cpus' supports a list of ranges (0-3), - # seperated by commas, and negation, (^1). - # Precedence is settled by order of the - # string: - # "0-3,^1" -> [0,2,3] - # "0-3,^1,1" -> [0,1,2,3] + # Conversion examples: + # vcpus=1: + # "1" -> [[1]] + # "0-3,^1" -> [[0,2,3]] + # vcpus=2: + # "1" -> [[1],[1]] + # "0-3,^1" -> [[0,2,3],[0,2,3]] try: - for c in cfg['cpus'].split(','): - if c.find('-') != -1: - (x, y) = c.split('-') - for i in range(int(x), int(y)+1): - cpus.append(int(i)) - else: - # remove this element from the list - if c[0] == '^': - cpus = [x for x in cpus if x != int(c[1:])] - else: - cpus.append(int(c)) - - cfg['cpus'] = cpus + cpus = cnv(cfg['cpus']) + for v in range(0, cfg['vcpus']): + cpus_list.append(cpus) except ValueError, e: raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) + else: + # Generation examples: + # vcpus=1: + # -> [[]] + # vcpus=2: + # -> [[],[]] + for v in range(0, cfg['vcpus']): + cpus_list.append(list()) + + cfg['cpus'] = cpus_list # Parse cpuid if 'cpuid' in cfg: diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 6e93795675..39e49d13ac 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -1365,28 +1365,25 @@ class XendDomain: raise XendInvalidDomain(str(domid)) # if vcpu is keyword 'all', apply the cpumap to all vcpus - vcpus = [ vcpu ] if str(vcpu).lower() == "all": vcpus = range(0, int(dominfo.getVCpuCount())) + else: + vcpus = [ int(vcpu) ] # set the same cpumask for all vcpus rc = 0 - if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - for v in vcpus: - try: - rc = xc.vcpu_setaffinity(dominfo.getDomid(), int(v), cpumap) - except Exception, ex: - log.exception(ex) - raise XendError("Cannot pin vcpu: %s to cpu: %s - %s" % \ - (v, cpumap, str(ex))) - else: - # FIXME: if we could define cpu affinity definitions to - # each vcpu, reprogram the following processing. - if str(vcpu).lower() != "all": - raise XendError("Must specify 'all' to VCPU " - "for inactive managed domains") - dominfo.setCpus(cpumap) - self.managed_config_save(dominfo) + cpus = dominfo.getCpus() + for v in vcpus: + try: + if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): + rc = xc.vcpu_setaffinity(dominfo.getDomid(), v, cpumap) + cpus[v] = cpumap + except Exception, ex: + log.exception(ex) + raise XendError("Cannot pin vcpu: %d to cpu: %s - %s" % \ + (v, cpumap, str(ex))) + dominfo.setCpus(cpus) + self.managed_config_save(dominfo) return rc diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index f121cdb6fc..607a97aef5 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1051,8 +1051,8 @@ class XendDomainInfo: ['running', 0], ['cpu_time', 0.0], ['cpu', -1], - ['cpumap', self.info['cpus'] and \ - self.info['cpus'] or range(64)]]) + ['cpumap', self.info['cpus'][i] and \ + self.info['cpus'][i] or range(64)]]) return sxpr @@ -1477,6 +1477,13 @@ class XendDomainInfo: self.info['VCPUs_live'] = vcpus self._writeDom(self._vcpuDomDetails()) else: + if self.info['VCPUs_max'] > vcpus: + # decreasing + del self.info['cpus'][vcpus:] + elif self.info['VCPUs_max'] < vcpus: + # increasing + for c in range(self.info['VCPUs_max'], vcpus): + self.info['cpus'].append(list()) self.info['VCPUs_max'] = vcpus xen.xend.XendDomain.instance().managed_config_save(self) log.info("Set VCPU count on domain %s to %d", self.info['name_label'], @@ -2071,9 +2078,17 @@ class XendDomainInfo: # repin domain vcpus if a restricted cpus list is provided # this is done prior to memory allocation to aide in memory # distribution for NUMA systems. - if self.info['cpus'] is not None and len(self.info['cpus']) > 0: + def has_cpus(): + if self.info['cpus'] is not None: + for c in self.info['cpus']: + if c: + return True + return False + + if has_cpus(): for v in range(0, self.info['VCPUs_max']): - xc.vcpu_setaffinity(self.domid, v, self.info['cpus']) + if self.info['cpus'][v]: + xc.vcpu_setaffinity(self.domid, v, self.info['cpus'][v]) else: def find_relaxed_node(node_list): import sys